home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / MA3.1.1 & CW4.5 / Modifications / *OR* replace these files / UMemory.cp < prev    next >
Encoding:
Text File  |  1994-09-17  |  53.5 KB  |  2,048 lines  |  [TEXT/MPS ]

  1. /*
  2. *    This file has been changed from the original MacApp 3.1.1
  3. *    to support the metrowerks CodeWarrior compilers C/C++ 1.1.1.
  4. *    These changes are known *not* to work with earlier versions
  5. *    of CodeWarrior.  Every attempt though has been made to to keep 
  6. *    this file compatible with other development environments.
  7. *
  8. *    Mark Anderson
  9. *    metrowerks
  10. *    9/16/94
  11. *
  12. */
  13.  
  14. //----------------------------------------------------------------------------------------
  15. // UMemory.cp
  16. // Copyright Â© 1985-1994 by Apple Computer, Inc.  All rights reserved.
  17. //----------------------------------------------------------------------------------------
  18.  
  19. #ifndef __UMEMORY__
  20. #include "UMemory.h"
  21. #endif
  22.  
  23. #ifndef __STDIO__
  24. #include <stdio.h>
  25. #endif
  26.  
  27. #ifndef __UFAILURE__
  28. #include "UFailure.h"
  29. #endif
  30.  
  31. #ifndef __MEMORY__
  32. #include "Memory.h"
  33. #endif
  34.  
  35. #ifndef __OBJECTHEAP__
  36. #include "ObjectHeap.h"
  37. #endif
  38.  
  39. #ifndef __TEXTEDIT__
  40. #include "TextEdit.h"
  41. #endif
  42.  
  43. #ifndef __OSUTILS__
  44. #include "OSUtils.h"
  45. #endif
  46.  
  47. #ifndef __UMACAPPUTILITIES__
  48. #include "UMacAppUtilities.h"
  49. #endif
  50.  
  51. #ifndef __TRAPS__
  52. #include "Traps.h"
  53. #endif
  54.  
  55. #ifndef __DEVICES__
  56. #include "Devices.h"
  57. #endif
  58.  
  59. #ifndef __TOOLUTILS__
  60. #include "ToolUtils.h"
  61. #endif
  62.  
  63. #ifndef __RESOURCES__
  64. #include "Resources.h"
  65. #endif
  66.  
  67. #ifndef __PACKAGES__
  68. #include "Packages.h"
  69. #endif
  70.  
  71. #ifndef __ERRORS__
  72. #include "Errors.h"
  73. #endif
  74.  
  75. #ifndef __UDEBUG__
  76. #include "UDebug.h"
  77. #endif
  78.  
  79. #ifndef __SEGLOAD__
  80. #include "SegLoad.h"
  81. #endif
  82.  
  83. #if qModelFarCode
  84.     #ifndef __RTLIB__
  85.     #include "RtLib.h"
  86.     #endif
  87. #endif
  88.  
  89. #if qDebugMsg
  90.     #ifndef __STDIO__
  91.     #include <stdio.h>
  92.     #endif
  93. #endif
  94.  
  95. #ifndef __LOWMEM__
  96. #include <LowMem.h>
  97. #endif
  98.  
  99. //----------------------------------------------------------------------------------------
  100. // Globals to this module and externally available.
  101.  
  102. ObjectHeap* gObjectHeap;
  103.  
  104. Size gMaxLockedRsrc;
  105. HandleListHandle gSysMemList;
  106. HandleListHandle gApp1MemList;
  107. HandleListHandle gApp2MemList;
  108.  
  109. short gCodeRefNum;
  110.  
  111. #if !qPowerPC
  112. HandleListHandle gCodeSegs;
  113. BoolListHandle gIsLoadedSeg;
  114. BoolListHandle gIsResidentSeg;
  115. #endif
  116.  
  117. // Used to be able to enable/disable the calculation of seg! resources in non-debug mode.
  118.  
  119. Boolean gCheckRsrcUsage = false;
  120.  
  121. // Static, globals to this module. Many of these are static by convention, but we don't
  122. // declare them as static because people may want to examine them.
  123.  
  124. #if !qPowerPC
  125. Boolean gUnloadAllSegs;
  126. #endif
  127.  
  128. UniversalProcPtr gGZPurgeNotify;
  129.  
  130. #if !qPowerPC
  131. LongListHandle pSegSize;
  132. #endif
  133.  
  134. Handle pCodeReserve;
  135. Handle pMemReserve;
  136. Boolean pOKCodeReserve;
  137. Boolean pPermAllocation;
  138. Boolean pReserveExists;
  139.  
  140. #if qDebug
  141. long pReserveShortfall;
  142. #endif
  143.  
  144. Size pSzCodeReserve;
  145. Size pSzMemReserve;
  146. TrapPatch pSegLoadPatch;
  147. short pOldResFile;
  148. Boolean pLoadSegCalledFromOwnApp;
  149.  
  150. #if !qPowerPC
  151. short pMaxSegNum;
  152. #endif
  153.  
  154. // local private globals
  155. static Boolean pDuringGrowZone;
  156. #if qModelFarCode
  157. static SegLoadHdlrPtr oldPreLoadHandler;
  158. static SegLoadHdlrPtr oldPostLoadHandler;
  159. #endif
  160.  
  161. // Function prototypes for some routines in this module.
  162.  
  163. pascal long GrowZoneProc(Size needed);
  164.  
  165. // Function prototypes for the routines in UMemory.a
  166.  
  167. #if !qPowerPC
  168. pascal void ALoadMacAppSeg();
  169. #endif
  170.  
  171. // LoadSeg is Patched to call ALoadMacAppSeg, which in turn calls LoadMacAppSegment.
  172. // ALoadMacAppSeg can only be referenced as a procedure pointer, because no args are
  173. // declared
  174.  
  175. typedef pascal void (*NotifyType)(Handle h);
  176.  
  177. #if qModelFarCode
  178. typedef pascal short (*HandlerType)(RTState* state);
  179. #endif
  180.  
  181.  
  182. //----------------------------------------------------------------------------------------
  183. //----------------------------------------------------------------------------------------
  184. //----------------------------------------------------------------------------------------
  185.  
  186.  
  187. //----------------------------------------------------------------------------------------
  188.  
  189. // These "MAFoo" functions were originally for THINK Pascal compatibility (but useful in the
  190. // larger problem of multiple open resource maps in general); when running under the THINK
  191. // environment, CODE resources are not found in the same resource file as other
  192. // application resources, so a UseResFile call needs to be made to bring the project
  193. // resource file into the search path. "gCodeRefNum" is set up at initialization time.
  194.  
  195. //----------------------------------------------------------------------------------------
  196.  
  197.  
  198. //----------------------------------------------------------------------------------------
  199. // MAGet1Resource: 
  200. //----------------------------------------------------------------------------------------
  201. #pragma segment MAMemoryRes
  202.  
  203. Handle MAGet1Resource(ResType rType, short rID)
  204. {
  205.     short oldResFile;
  206.     Handle resource;
  207.  
  208.     oldResFile = MAUseResFile(gCodeRefNum);
  209.     resource = Get1Resource(rType, rID);
  210.     MAUseResFile(oldResFile);
  211.  
  212.     return resource;
  213. } // MAGet1Resource 
  214.  
  215. //----------------------------------------------------------------------------------------
  216. // MAGet1NamedResource: 
  217. //----------------------------------------------------------------------------------------
  218. #pragma segment MAMemoryRes
  219.  
  220. Handle MAGet1NamedResource(ResType rType, const CStr255 &name)
  221. {
  222.     short oldResFile;
  223.     Handle namedResource;
  224.  
  225.     oldResFile = MAUseResFile(gCodeRefNum);
  226.     namedResource = Get1NamedResource(rType, name);
  227.     MAUseResFile(oldResFile);
  228.  
  229.     return namedResource;
  230. } // MAGet1NamedResource 
  231.  
  232. //----------------------------------------------------------------------------------------
  233. // MAGet1IndResource: 
  234. //----------------------------------------------------------------------------------------
  235. #pragma segment MAMemoryRes
  236.  
  237. Handle MAGet1IndResource(ResType rType, short index)
  238. {
  239.     short oldResFile;
  240.     Handle indResource;
  241.  
  242.     oldResFile = MAUseResFile(gCodeRefNum);
  243.     indResource = Get1IndResource(rType, index);
  244.     MAUseResFile(oldResFile);
  245.  
  246.     return indResource;
  247. } // MAGet1IndResource 
  248.  
  249. //----------------------------------------------------------------------------------------
  250. // MACount1Resources: 
  251. //----------------------------------------------------------------------------------------
  252. #pragma segment MAMemoryRes
  253.  
  254. short MACount1Resources(ResType rType)
  255. {
  256.     short oldResFile;
  257.     short resourceCnt;
  258.  
  259.     oldResFile = MAUseResFile(gCodeRefNum);
  260.     resourceCnt = Count1Resources(rType);
  261.     MAUseResFile(oldResFile);
  262.  
  263.     return resourceCnt;
  264. } // MACount1Resources 
  265.  
  266. //----------------------------------------------------------------------------------------
  267. // MAGetResource: 
  268. //----------------------------------------------------------------------------------------
  269. #pragma segment MAMemoryRes
  270.  
  271. Handle MAGetResource(ResType rType, short rID)
  272. {
  273.     Handle h;
  274.     short oldResFile;
  275.  
  276.     oldResFile = MAUseResFile(gCodeRefNum);
  277.     h = GetResource(rType, rID);
  278.     MAUseResFile(oldResFile);
  279.  
  280.     return h;
  281. } // MAGetResource 
  282.  
  283. //----------------------------------------------------------------------------------------
  284. // MAGetNamedResource: 
  285. //----------------------------------------------------------------------------------------
  286. #pragma segment MAMemoryRes
  287.  
  288. Handle MAGetNamedResource(ResType rType, const CStr255 &name)
  289. {
  290.     Handle h;
  291.     short oldResFile;
  292.  
  293.     oldResFile = MAUseResFile(gCodeRefNum);
  294.     h = GetNamedResource(rType, name);
  295.     MAUseResFile(oldResFile);
  296.  
  297.     return h;
  298. } // MAGetNamedResource 
  299.  
  300. //----------------------------------------------------------------------------------------
  301. // MAGetIndResource: 
  302. //----------------------------------------------------------------------------------------
  303. #pragma segment MAMemoryRes
  304.  
  305. Handle MAGetIndResource(ResType rType, short index)
  306. {
  307.     Handle h;
  308.     short oldResFile;
  309.  
  310.     oldResFile = MAUseResFile(gCodeRefNum);
  311.     h = GetIndResource(rType, index);
  312.     MAUseResFile(oldResFile);
  313.  
  314.     return h;
  315. } // MAGetIndResource 
  316.  
  317. //----------------------------------------------------------------------------------------
  318. // MACountResources: 
  319. //----------------------------------------------------------------------------------------
  320. #pragma segment MAMemoryRes
  321.  
  322. short MACountResources(ResType rType)
  323. {
  324.     short oldResFile;
  325.     short resourceCnt;
  326.  
  327.     oldResFile = MAUseResFile(gCodeRefNum);
  328.     resourceCnt = CountResources(rType);
  329.     MAUseResFile(oldResFile);
  330.  
  331.     return resourceCnt;
  332. } // MACountResources 
  333.  
  334. //----------------------------------------------------------------------------------------
  335. // GetSegResource: 
  336. //----------------------------------------------------------------------------------------
  337. #pragma segment MAMemoryRes
  338.  
  339. Handle GetSegResource(short segnum)
  340. {
  341.     return MAGet1Resource(kCode, segnum);
  342. } // GetSegResource 
  343.  
  344. //----------------------------------------------------------------------------------------
  345. // AddAllRsrc: 
  346. //----------------------------------------------------------------------------------------
  347. #pragma segment MAMiniInit
  348.  
  349. void AddAllRsrc(ResType rType, HandleListHandle toList)
  350. {
  351.     short oldResLoad = LMGetResLoad();
  352.     SetResLoad(false);
  353.  
  354.     short nResources = CountResources(rType);
  355.     for (short i = 1; i <= nResources; ++i)
  356.     {
  357.         short theID;
  358.         Handle h;
  359.         ResType theType;
  360.         Str255 theName;
  361.  
  362.         h = GetIndResource(rType, i);
  363.         GetResInfo(h, &theID, &theType, theName);
  364.  
  365.         // If there is a ROM resource for this type and ID, don't put it
  366.         // on the list since it will not consume any memory.
  367.  
  368.         UseROMMap(false);
  369.         h = GetResource(rType, theID);
  370.         UseROMMap(true);
  371.         if ((h) && (HomeResFile(h) != 1))
  372.             AddHandle(h, toList);
  373.     }
  374.  
  375.     SetResLoad(oldResLoad);
  376. } // AddAllRsrc 
  377.  
  378. //----------------------------------------------------------------------------------------
  379. // AddHandle: 
  380. //----------------------------------------------------------------------------------------
  381. #pragma segment MAMiniInit
  382.  
  383. void AddHandle(Handle h, HandleListHandle toList)
  384. {
  385.     long offset;
  386.  
  387.     offset = Munger((Handle)toList, 0, NULL, 0, &h, 4);
  388.     FailMemError();
  389. } // AddHandle 
  390.  
  391. //----------------------------------------------------------------------------------------
  392. // AddSegSizes: 
  393. //----------------------------------------------------------------------------------------
  394. #pragma segment MAMiniInit
  395.  
  396. Size AddSegSizes(Handle segRsrc)
  397. {
  398.     SignedByte savedState;
  399.     SignedBytePtr p;
  400.     short oldResLoad;
  401.     register long total;
  402.     Handle seg;
  403.     short i;
  404.     CStr255 s;
  405.  
  406.     savedState = LockHandleHigh(segRsrc);
  407.  
  408.     oldResLoad = LMGetResLoad();
  409.     SetResLoad(false);
  410.  
  411.     p = (SignedBytePtr) * segRsrc;
  412.     i = *((IntegerPtr)p);
  413.     p += 2;
  414.  
  415.     total = 0;
  416.  
  417.     for (; i > 0; i--, p += *p + 1)
  418.     {
  419.         BlockMove(p, &s, *p + 1);
  420.         seg = MAGet1NamedResource(kCode, s);
  421.         if (seg)
  422.             total += GetResourceSizeOnDisk(seg) + 8;
  423.     }
  424.  
  425.     SetResLoad(oldResLoad);
  426.     HSetState(segRsrc, savedState);
  427.  
  428.     return total;
  429. } // AddSegSizes 
  430.  
  431. //----------------------------------------------------------------------------------------
  432. // IsHandleEligible: 
  433. //----------------------------------------------------------------------------------------
  434. #pragma segment MAMemoryRes
  435.  
  436. Boolean IsHandleEligible(Handle h)
  437. {
  438.     if (h == NULL)
  439.         return false;                            // Thanks Pillar! 
  440.     else if (IsHandlePurged(h))
  441.         return false;
  442.     else
  443.         return (h != LMGetGZMoveHnd()) && (h != LMGetGZRootHnd());
  444. } // IsHandleEligible 
  445.  
  446. //----------------------------------------------------------------------------------------
  447. // BuildCodeReserve: 
  448. //----------------------------------------------------------------------------------------
  449. #pragma segment MAMemoryRes
  450.  
  451. void BuildCodeReserve(Size allocLim, Boolean fromGZ)
  452. {
  453.     static const short initVal = 0xF7;
  454.  
  455.     Size needed,  avail;
  456.     Handle canPurge = 0;
  457. #if qDebug
  458.     Size theSize;
  459. #endif
  460.  
  461.     pOKCodeReserve = true;                        // default value 
  462.  
  463. #if qDebug
  464.     pReserveShortfall = 0;
  465.  
  466.     if (!pPermAllocation)
  467.         ProgramBreak("BuildCodeReserve called with pPermAllocation = false");
  468. #endif
  469.  
  470.     if (!pReserveExists)
  471.     {
  472.         // free the current code reserve 
  473.         if (IsHandleEligible(pCodeReserve))
  474.         {
  475.             EmptyHandle(pCodeReserve);
  476.             pReserveExists = false;
  477.         }
  478.  
  479.         // compute amt actually needed 
  480.         needed = Min(pSzCodeReserve - TotalTempSize(false, canPurge) - 8, allocLim);
  481.  
  482.         if (needed > 0)
  483.         {
  484.             // make as much memory available as possible 
  485.             if (IsHandleEligible(pMemReserve))
  486.                 EmptyHandle(pMemReserve);
  487.  
  488.             if (fromGZ)                            // Never purge or compact from GrowZone 
  489.                 avail = allocLim;
  490.             else
  491.                 {
  492.                 PurgeMem(needed);
  493.                 avail = CompactMem(needed);
  494.             }
  495.             
  496.             if (avail < needed)                    // could not get the whole reserve 
  497.             {
  498. #if qDebug
  499.                 pReserveShortfall = needed - avail;
  500. #endif
  501.  
  502.                 pOKCodeReserve = false;
  503.                 pReserveExists = false;
  504.  
  505.                 needed = avail;                    // get the most we can 
  506.             }
  507.  
  508. #if !qPowerPC
  509.             if (!fromGZ && (IsHandlePurged(pCodeReserve) || IsHandleEligible(pCodeReserve)))
  510.             {
  511.                 ReallocateHandle(pCodeReserve, needed);
  512.                 if (MemError() == noErr)
  513.                     pReserveExists = true;
  514.             }
  515.             
  516. #if qDebug
  517.             theSize = GetHandleSize(pCodeReserve);
  518.             if (theSize != 0)
  519.                 BlockSet(*pCodeReserve, theSize, initVal);
  520. #endif
  521.  
  522.             if (!IsHandlePurged(pCodeReserve))
  523.             {
  524.                 // Large handles are almost as bad as nonrelocatable blocks. Try to get
  525.                 // this guy out of the way, just in case.
  526.  
  527.                 if (!fromGZ)
  528.                     MoveHHi(pCodeReserve);
  529.             }
  530. #endif    // if !qPowerPC
  531.         }
  532.     }
  533. } // BuildCodeReserve 
  534.  
  535. //----------------------------------------------------------------------------------------
  536. // BuildAllReserves: 
  537. //----------------------------------------------------------------------------------------
  538. #pragma segment MAMemoryRes
  539.  
  540. void BuildAllReserves()
  541. {
  542.     static const short initVal = 0xF7;
  543.  
  544.     Boolean oldPerm;
  545. #if qDebug
  546.     Size theSize;
  547. #endif
  548.  
  549.     // set the permanent flag to ensure that the code reserve is actually allocated and
  550.     // not given up to the low space reserve
  551.  
  552.     oldPerm = pPermAllocation;
  553.     pPermAllocation = true;
  554.  
  555.     BuildCodeReserve(kGZMaxAlloc, false);        // make sure code reserve is OK
  556.  
  557.     // reallocate the low space handle, if necessary
  558.  
  559.     if (IsHandlePurged(pMemReserve))
  560.     {
  561.         ReallocateHandle(pMemReserve, pSzMemReserve);
  562. #if qDebug
  563.         theSize = GetHandleSize(pMemReserve);
  564.         if (theSize != 0)
  565.             BlockSet(*pMemReserve, theSize, initVal);
  566. #endif
  567.  
  568.     }
  569.  
  570.     pPermAllocation = oldPerm;                    // reset the permanent flag 
  571. } // BuildAllReserves 
  572.  
  573. //----------------------------------------------------------------------------------------
  574. // CheckReserve: 
  575. //----------------------------------------------------------------------------------------
  576. #pragma segment MAMemoryRes
  577.  
  578. Boolean CheckReserve()
  579. {
  580.     BuildAllReserves();
  581.     return pOKCodeReserve;
  582. } // CheckReserve 
  583.  
  584. //----------------------------------------------------------------------------------------
  585. // CheckRsrcUsage: 
  586. //----------------------------------------------------------------------------------------
  587. #pragma segment MAMemoryRes
  588.  
  589. void CheckRsrcUsage()
  590. {
  591.     long sz;
  592.     Handle h;
  593.     CStr255 s;
  594.  
  595.     sz = TotalTempSize(true, h);
  596.     if (sz > gMaxLockedRsrc)
  597.     {
  598.         // In non debug mode, one can calculate seg! resources by loading the application
  599.         // under SADE, setting the variable gCheckRsrcUsage to true, and setting a break
  600.         // point on the following line. Everytime SADE breaks on this line, you can use
  601.         // the heap command to look at your loaded segments.
  602.  
  603.         gMaxLockedRsrc = sz;
  604.  
  605. #if qDebug
  606.         if (gRsrcReport)
  607.         {
  608.             ShowSegments();
  609.             NumToString(gMaxLockedRsrc, s);
  610.             s = "  = New maximum resources usage: " + s + " =";
  611.             ProgramReport(s, gMemMgtBreak);
  612.         }
  613. #endif
  614.  
  615.     }
  616. } // CheckRsrcUsage 
  617.  
  618. //----------------------------------------------------------------------------------------
  619. // DoInitUMemory: Called from InitUMemory so that InitUMemory can be in the main segment
  620. // and this code can be in another (unloadable) segment.
  621. //----------------------------------------------------------------------------------------
  622. #pragma segment MAMiniInit
  623.  
  624. void DoInitUMemory(Size &sizeObjectHeap,
  625.                    Size &sizeHeapIncrement,
  626.                    Size &sizeTempReserve,
  627.                    Size &sizeLowSpaceReserve)
  628. {
  629. #if defined(powerc) || defined (__powerc)
  630. #pragma options align=mac68k
  631. #endif
  632.     struct Mem
  633.     {
  634.         long objectHeap, heapIncrement, codeVal, lowSpaceVal, stackVal;
  635.     };
  636. #if defined(powerc) || defined(__powerc)
  637. #pragma options align=reset
  638. #endif
  639.  
  640.     typedef Mem *MemPtr, 
  641.     **MemHandle;
  642.  
  643.     short i, 
  644.     rsrcCnt;
  645.     short oldResLoad;
  646.     Handle seg,  h;
  647.     long stackTot;
  648.     short rsrcID;
  649.     ResType rsrcType;
  650.     Str255 rsrcName;
  651.     short lastRsrc;
  652.     short mainSegment,  utilitySegment;
  653.  
  654.     // Initialize memory management globals
  655.  
  656.     pPermAllocation = false;
  657.     pMemReserve = NewHandle(0);
  658.     FailNIL(pMemReserve);
  659.  
  660.     pSzMemReserve = 0;
  661.     pCodeReserve = NewHandle(0);
  662.     FailNIL(pCodeReserve);
  663.  
  664.     pSzCodeReserve = 0;
  665.     gGZPurgeNotify = NULL;
  666.     pOKCodeReserve = true;
  667.     pReserveExists = false;
  668.  
  669. #if !qPowerPC
  670.     gUnloadAllSegs = true;
  671. #endif
  672.  
  673.     gCodeRefNum = LMGetCurApRefNum();
  674.     
  675. #if !qPowerPC
  676.     pMaxSegNum = 0;
  677.  
  678.     //###########################################
  679.     // No resource loading 
  680.  
  681.     oldResLoad = LMGetResLoad();
  682.     SetResLoad(false);
  683.  
  684.     // Figure the highest segment number 
  685.     lastRsrc = MACount1Resources(kCode);
  686.  
  687.     // some development systems may not have contiguous numbering of CODE segments. try to
  688.     // be polite about handling it
  689.  
  690.     for (i = 1; i <= lastRsrc; ++i)
  691.     {
  692.         seg = MAGet1IndResource(kCode, i);
  693.  
  694.         // we only have an index find the real resource ID and keep track of the highest one
  695.  
  696.         if (seg)
  697.         {
  698.             GetResInfo(seg, &rsrcID, &rsrcType, rsrcName);
  699.             pMaxSegNum = (short)Max(rsrcID, pMaxSegNum);
  700.         }
  701.     }
  702.  
  703.     SetResLoad(oldResLoad);                        // in case of failure 
  704.  
  705.     // Allocate the master segment lists.
  706.     gCodeSegs = (HandleListHandle)NewHandle(pMaxSegNum * sizeof(Handle));
  707.     FailNIL(gCodeSegs);
  708.  
  709.     gIsResidentSeg = (BoolListHandle)NewHandle(pMaxSegNum * sizeof(Boolean));
  710.     FailNIL(gIsResidentSeg);
  711.  
  712.     gIsLoadedSeg = (BoolListHandle)NewHandle(pMaxSegNum * sizeof(Boolean));
  713.     FailNIL(gIsLoadedSeg);
  714.  
  715.     /* (NOTE: assumes application doesn't change the CODE segment size at runtime
  716.       (a very safe assumption)). Used in GetSegFromPC. */
  717.  
  718.     pSegSize = (LongListHandle)NewHandle(pMaxSegNum * sizeof(long));
  719.     FailNIL(pSegSize);
  720.     
  721.     oldResLoad = LMGetResLoad();                    // OK, suppress segment loading again 
  722.     SetResLoad(false);
  723.  
  724.     // Segments and their sizes and actual loaded state (helps catch preloads)
  725.  
  726.     for (i = 0; i < pMaxSegNum; ++i)
  727.     {
  728.         (*gIsResidentSeg)[i] = false;
  729.         seg = GetSegResource(i + 1);
  730.         (*gCodeSegs)[i] = seg;
  731.         if (seg)                                // seg is non-nil if the segment number
  732.             (*pSegSize)[i] = GetResourceSizeOnDisk(seg);
  733.         else
  734.             (*pSegSize)[i] = 0;
  735.  
  736.         (*gIsLoadedSeg)[i] = true;                // Assume all segments are loaded
  737.     }
  738.  
  739.     SetResLoad(oldResLoad);
  740.     //###########################################
  741.  
  742.     mainSegment = GetSegNumber((ProcPtr) & InitUMemory);// Main is always resident 
  743.     (*gIsResidentSeg)[mainSegment - 1] = true;
  744.  
  745.     utilitySegment = GetSegNumber((ProcPtr) & UnloadAllSegments);// Utilities are always resident 
  746.     (*gIsResidentSeg)[utilitySegment - 1] = true;
  747.  
  748. #ifdef __MWERKS__ // __%Main must be resident
  749.     (*gIsResidentSeg)[0] = true;
  750. #endif    
  751.  
  752. #if qModelFarCode
  753.     
  754.     //    (*gIsResidentSeg)[pMaxSegNum - 1] = true;    // 32-bit bootstrap is always last
  755.                                                     // _AND_ resident
  756.                                                     // THIS IS NOT TRUE. With ILink,
  757.                                                     // 32-bit bootstrap is segment 2. 
  758.     
  759.     {
  760.         CStr255 name("32-bit bootstrap");
  761.         Handle seg = MAGet1NamedResource(kCode, name);
  762.         if (seg)
  763.         {
  764.             short segnum;
  765.             ResType theType;
  766.             
  767.             GetResInfo(seg, &segnum, &theType, name);
  768.             (*gIsResidentSeg)[segnum - 1] = true;
  769.         }
  770.     }
  771. #endif
  772. #endif
  773.  
  774.     // init the gSysMemList 
  775.  
  776.     gSysMemList = (HandleListHandle)NewHandle(0);
  777.     FailNIL(gSysMemList);
  778.  
  779.     AddAllRsrc('LDEF', gSysMemList);
  780.     AddAllRsrc('CDEF', gSysMemList);
  781.     AddAllRsrc('MDEF', gSysMemList);
  782.     AddAllRsrc('WDEF', gSysMemList);
  783.     AddAllRsrc('PACK', gSysMemList);
  784.  
  785.     // Compute memory slop needed
  786.  
  787.     sizeObjectHeap = 0;
  788.     sizeHeapIncrement = 0;
  789.     sizeTempReserve = 0;
  790.     sizeLowSpaceReserve = 0;
  791.     stackTot = 0;
  792.  
  793. #if !qPowerPC
  794.     rsrcCnt = CountResources('seg!');
  795.     for (i = 1; i <= rsrcCnt; ++i)
  796.     {
  797.         h = GetIndResource('seg!', i);
  798.         sizeTempReserve += AddSegSizes(h);
  799.         ReleaseResource(h);
  800.     }
  801. #endif
  802.  
  803.     // Sum up the standard memory requirements
  804.     
  805.     rsrcCnt = CountResources('mem!');
  806.     for (i = 1; i <= rsrcCnt; ++i)
  807.     {
  808.         h = GetIndResource('mem!', i);
  809.         {
  810.             const Mem &memH = **((MemHandle)h);
  811.  
  812.             sizeObjectHeap += memH.objectHeap;
  813.             sizeHeapIncrement += memH.heapIncrement;
  814.             sizeTempReserve += memH.codeVal;
  815.             sizeLowSpaceReserve += memH.lowSpaceVal;
  816.             stackTot += memH.stackVal;
  817.         }
  818.         ReleaseResource(h);
  819.     }
  820.     
  821.     // Add on the processor dependent memory requirements
  822.  
  823. #if qPowerPC
  824.     const ResType kCPUmemResType = 'ppc!';
  825. #else
  826.     const ResType kCPUmemResType = '68k!';
  827. #endif
  828.  
  829.     rsrcCnt = CountResources(kCPUmemResType);
  830.     for (i = 1; i <= rsrcCnt; ++i)
  831.     {
  832.         h = GetIndResource(kCPUmemResType, i);
  833.         {
  834.             const Mem &memH = **((MemHandle)h);
  835.  
  836.             sizeObjectHeap += memH.objectHeap;
  837.             sizeHeapIncrement += memH.heapIncrement;
  838.             sizeTempReserve += memH.codeVal;
  839.             sizeLowSpaceReserve += memH.lowSpaceVal;
  840.             stackTot += memH.stackVal;
  841.         }
  842.         ReleaseResource(h);
  843.     }
  844.  
  845.     SetStackSpace(stackTot);
  846.  
  847.     MaxApplZone();
  848.  
  849.     gApp1MemList = NULL;
  850.     gApp2MemList = NULL;
  851.  
  852. } // DoInitUMemory 
  853.  
  854. //----------------------------------------------------------------------------------------
  855. // FailNoReserve: 
  856. //----------------------------------------------------------------------------------------
  857. #pragma segment MAMemoryRes
  858.  
  859. void FailNoReserve()
  860. {
  861.     if (!CheckReserve())
  862.         Failure(memFullErr, 0);
  863. } // FailNoReserve 
  864.  
  865. //----------------------------------------------------------------------------------------
  866. // FailSpaceIsLow: 
  867. //----------------------------------------------------------------------------------------
  868. #pragma segment MAMemoryRes
  869.  
  870. void FailSpaceIsLow()
  871. {
  872.     if (MemSpaceIsLow())
  873.         Failure(memFullErr, 0);
  874. } // FailSpaceIsLow 
  875.  
  876. //----------------------------------------------------------------------------------------
  877. // GetReserveSize: 
  878. //----------------------------------------------------------------------------------------
  879. #pragma segment MAMemoryRes
  880.  
  881. void GetReserveSize(Size &szCodeReserve, Size &szMemReserve)
  882. {
  883.     szCodeReserve = pSzCodeReserve;
  884.     szMemReserve = pSzMemReserve;
  885. } // GetReserveSize 
  886.  
  887. //----------------------------------------------------------------------------------------
  888. // GetSegFromPC: 
  889. //----------------------------------------------------------------------------------------
  890. #if !qPowerPC
  891. #pragma segment MAMemoryRes
  892.  
  893. // Shouldn't be unloaded 
  894.  
  895. short GetSegFromPC(void* pc)
  896. {
  897.     long segStart;
  898.     short i;
  899.     Handle seg;
  900.  
  901.     // Since GetSegFromPC may be called before gCodeSegs is set up, we have to test if
  902.     // gCodeSegs == NULL before using it.
  903.  
  904.     if (gCodeSegs)
  905.         for (i = 0; i < pMaxSegNum; ++i)
  906.         {
  907.             seg = (*gCodeSegs)[i];                // get segment handle 
  908.             if ((seg) &&!IsHandlePurged(seg))    // it's in memory 
  909.             {
  910.                 segStart = StripLong(*seg);        // get segment start 
  911.                 if (((long) pc >= segStart) && ((long) pc < segStart + (*pSegSize)[i]))
  912.                     return i + 1;
  913.             }
  914.         }
  915.  
  916.     return 0;                                    // default return
  917. } // GetSegFromPC 
  918. #endif
  919.  
  920. #if !qPowerPC
  921. #if qModelFarCode
  922.  
  923. //----------------------------------------------------------------------------------------
  924. // GetSegNumber: Gets seg number from a Jump table address.
  925. //
  926. // Must be in Main segment because we call this in order to make the resident segment
  927. // resident.
  928. //----------------------------------------------------------------------------------------
  929. #pragma segment MAMemoryRes
  930. short GetSegNumber(ProcPtr aProc)
  931. {
  932.     static const short kLoaded = 0x4EF9;        // if loaded then a JMP instruction
  933.     static const short kUnLoaded = 0xA9F0;        // if unloaded then a _LoadSeg trap
  934.  
  935.     // Check for load and unloaded state, otherwise we are not pointing
  936.     // at a valid jump table entry. In a model far jump table entry the first
  937.     // two bytes are the segment number whether the segment is loaded or not.
  938.     
  939.     if (*((const short *)aProc) == kLoaded || *((const short *)aProc) == kUnLoaded)
  940.         return *((const short *)((const char *)aProc - 2));
  941.  
  942. #if qDebug
  943.     ProgramBreak("GetSegNumber was not passed an jump table address");
  944. #endif
  945.  
  946.     return 0;
  947. } // GetSegNumber 
  948.  
  949. #else
  950.  
  951. //----------------------------------------------------------------------------------------
  952. // GetSegNumber: 
  953. //----------------------------------------------------------------------------------------
  954. short GetSegNumber(ProcPtr aProc)
  955. {
  956.     static const short kLoaded = 0x4EF9;        // if loaded then a JMP instruction
  957. #ifdef __MWERKS__
  958.     static const short kUnLoaded = 0xA9F0;        // if loaded then a JMP instruction
  959.     const    short    offset = 6;
  960. #else
  961.     static const short kUnLoaded = 0x3F3C;        // if unloaded then a Move instruction (seg# onto stack)
  962.     const    short    offset = 2;
  963. #endif
  964.  
  965.     if (*((const short *)aProc) == kLoaded)        // loaded segment 
  966. #ifdef __MWERKS__
  967.         return *((const short *)((const char *) aProc + offset));
  968. #else
  969.         return *((const short *)((const char *) aProc - offset));
  970. #endif
  971.     else if (*((const short *)aProc) == kUnLoaded)    // unloaded segment 
  972.         return *((const short *)((const char *) aProc + offset));
  973.     else                                        /* routine that computed &proc was in same
  974.                                                   segment as the proc */
  975.     {
  976. #if qDebug
  977.         ProgramBreak("GetSegNumber was not passed an jump table address");
  978. #endif
  979.  
  980.         return 0;
  981.     }
  982. } // GetSegNumber 
  983.  
  984. #endif // qModelFarCode
  985. #endif // !qPowerPC
  986.  
  987. //----------------------------------------------------------------------------------------
  988. // GetSegSize: 
  989. //----------------------------------------------------------------------------------------
  990. #if !qPowerPC
  991. #pragma segment MAMemoryRes
  992.  
  993. Size GetSegSize(short segnum)
  994. {
  995.     return (*pSegSize)[segnum - 1];
  996. } // GetSegSize 
  997. #endif
  998.  
  999. //----------------------------------------------------------------------------------------
  1000. // GrowZoneProc: 
  1001. //----------------------------------------------------------------------------------------
  1002. #pragma push
  1003. #pragma trace off
  1004.  
  1005. #pragma segment MAMemoryRes
  1006.  
  1007. pascal long GrowZoneProc(Size)
  1008. {
  1009.     long result, 
  1010.     reserveSize, 
  1011.     OldA5;
  1012.     Handle canPurge;
  1013.     Size codeSize;
  1014.  
  1015.     OldA5 = SetCurrentA5();                        // Can be called from other worlds 
  1016.  
  1017.     result = 0;                                    // default is to fail 
  1018.  
  1019.     if (!pDuringGrowZone)                        // prevent re-entrancy 
  1020.     {
  1021.         pDuringGrowZone = true;
  1022.         
  1023. #if !qPowerPC
  1024.         // on a temp alloc, free all code slack immediately 
  1025.  
  1026.         if (!pPermAllocation && IsHandleEligible(pCodeReserve))
  1027.         {
  1028.             EmptyHandle(pCodeReserve);
  1029.             pReserveExists = false;
  1030.             result = 1;
  1031.         }
  1032.  
  1033.         if (result == 0)                        // try harder: see if we can purge a code
  1034.                                                 // segment or reduce the code reserve
  1035.                                                 // handle
  1036.         {
  1037.             // compute size of resources currently in memory 
  1038.  
  1039.             codeSize = TotalTempSize(false, canPurge);
  1040.  
  1041.             // see if the code reserve handle is too large 
  1042.  
  1043.             if (IsHandleEligible(pCodeReserve))
  1044.             // we have a code reserve handle; this implies permanent allocation, otherwise
  1045.             // the handle would have been emptied above
  1046.             {
  1047.                 reserveSize = GetHandleSize(pCodeReserve);
  1048.  
  1049.                 // the following test is an optimization to avoid calling BuildCodeReserve
  1050.                 // if there is no hope of reducing the code reserve handle
  1051.  
  1052.                 if (codeSize + reserveSize + 8 > pSzCodeReserve)
  1053.                 {
  1054.                     // reserve is too big 
  1055.                     pReserveExists = false;
  1056.                     // this should lower the code reserve 
  1057.                     BuildCodeReserve(reserveSize, true);
  1058.  
  1059.                     // see if we succeeded in freeing some memory 
  1060.                     if (IsHandlePurged(pCodeReserve))
  1061.                         result = 1;
  1062.                     else if (GetHandleSize(pCodeReserve) < reserveSize)
  1063.                         result = 1;
  1064.                 }
  1065.             }
  1066.  
  1067.             // got something; only purge it if this is temporary || we know there is too
  1068.             // much code in memory already
  1069.             
  1070.             if ((result == 0) && (canPurge) && (!pPermAllocation || IsHandlePurged(pCodeReserve)))
  1071.             {
  1072.                 if (gGZPurgeNotify)
  1073.                     ((NotifyType)gGZPurgeNotify)(canPurge);
  1074.  
  1075.                 reserveSize = GetHandleSize(canPurge);
  1076.                 HPurge(canPurge);
  1077.                 EmptyHandle(canPurge);
  1078.                 pReserveExists = false;
  1079.  
  1080.                 if (pPermAllocation)            // don't free too much however 
  1081.                     BuildCodeReserve(reserveSize, true);
  1082.  
  1083.                 result = 1;
  1084.             }
  1085.         }
  1086. #endif    // #if !qPowerPC
  1087.  
  1088.         // last ditch attempt-free emergency reserve
  1089.         if ((result == 0) && IsHandleEligible(pMemReserve))
  1090.         {
  1091.             EmptyHandle(pMemReserve);
  1092.             result = 1;
  1093.         }
  1094.  
  1095.         pDuringGrowZone = false;
  1096.     }
  1097.  
  1098.     OldA5 = SetA5(OldA5);
  1099.  
  1100.     return result;
  1101. } // GrowZoneProc 
  1102.  
  1103. #pragma pop
  1104.  
  1105. //----------------------------------------------------------------------------------------
  1106. // InstallGrowZoneProc: Once called the grow zone proc's segment CANNOT be moved since
  1107. // we're passing a NON-JT address to SetGrowZone (so we can be called from "other worlds"
  1108. //----------------------------------------------------------------------------------------
  1109. #pragma segment MAMemoryRes
  1110. // Must be in same segment as grow zone proc
  1111.  
  1112. void InstallGrowZoneProc()
  1113. {
  1114.     pDuringGrowZone = false;
  1115.  
  1116.     GrowZoneUPP gzUPP = NewGrowZoneProc(&GrowZoneProc);
  1117.     FailNIL(gzUPP);
  1118.     SetGrowZone(gzUPP);
  1119. } // InstallGrowZoneProc 
  1120.  
  1121. //----------------------------------------------------------------------------------------
  1122. // PreloadHandler: 
  1123. //----------------------------------------------------------------------------------------
  1124. #if !qPowerPC
  1125. #if qModelFarCode
  1126. #pragma segment MAMemoryRes
  1127.  
  1128. pascal short PreloadHandler(RTState* state)
  1129.  
  1130. {
  1131.     LoadMacAppSegment(state->fSegNo);
  1132.  
  1133.     if (oldPreLoadHandler)
  1134.         return ((HandlerType)oldPreLoadHandler)(state);
  1135.     else
  1136.         return 0;
  1137. } // PreloadHandler 
  1138. #endif
  1139. #endif
  1140.  
  1141. //----------------------------------------------------------------------------------------
  1142. // PostLoadMacAppSegment: 
  1143. //----------------------------------------------------------------------------------------
  1144. #if !qPowerPC
  1145. #pragma push
  1146. #pragma trace off
  1147.  
  1148. #pragma segment MAMemoryRes
  1149.  
  1150. // must be in Main segment 
  1151. // NOTE: this routine requires the pascal keyword because it is called from assembler
  1152. // code that assumes pascal parameter passing conventions.
  1153.  
  1154. pascal void PostLoadMacAppSegment()
  1155. {
  1156.     long A5RegisterOnEntry = SetCurrentA5();            // ***** Called from trap patches *****
  1157.     // test if called from our application… if so, don't do patch behaviour. Thank you McSink! 
  1158.     if (GetA5() == A5RegisterOnEntry && pLoadSegCalledFromOwnApp)
  1159.         MAUseResFile(pOldResFile);        // Called back from our glue.  Restores current res file pointer. 
  1160.     SetA5(A5RegisterOnEntry);
  1161. } // PostLoadMacAppSegment 
  1162.  
  1163. #pragma pop
  1164. #endif
  1165.  
  1166. //----------------------------------------------------------------------------------------
  1167. // PostloadHandler: 
  1168. //----------------------------------------------------------------------------------------
  1169. #if !qPowerPC
  1170. #if qModelFarCode
  1171. #pragma segment MAMemoryRes
  1172.  
  1173. pascal short PostloadHandler(RTState* state)
  1174.  
  1175. {
  1176.     PostLoadMacAppSegment();
  1177.     if (oldPostLoadHandler)
  1178.         return ((HandlerType)oldPostLoadHandler)(state);
  1179.     else
  1180.         return 0;
  1181. } // PostloadHandler 
  1182. #endif
  1183. #endif
  1184.  
  1185. //----------------------------------------------------------------------------------------
  1186. // InitUMemory: 
  1187. //----------------------------------------------------------------------------------------
  1188. #pragma segment Main
  1189. // Must be in main segment and called from main segment
  1190.  
  1191. void InitUMemory(short callsToMoreMasters)
  1192. {
  1193.     Size heapSize, heapIncrement, codeRes, lowSpaceRes = 0;
  1194.     THz applZone;
  1195.     short oldMoreMast;
  1196.  
  1197. #if !qPowerPC
  1198.     // Get these segments out of the way so that when DoInitUMemory gets called and the
  1199.     // next block of master pointers gets allocated they won't constipate the heap
  1200.  
  1201.     Handle miniInitSeg = GetResource(kCode, GetSegNumber((ProcPtr) & DoInitUMemory));
  1202.     if (miniInitSeg)
  1203.     {
  1204.         UnloadSeg(&DoInitUMemory);
  1205.         LockHandleHigh(miniInitSeg);
  1206.     }
  1207. #endif
  1208.  
  1209.     DoInitUMemory(heapSize, heapIncrement, codeRes, lowSpaceRes);
  1210.  
  1211. #if !qPowerPC
  1212.     UnloadAllSegments();                        // get init segment(s) out of middle of
  1213.                                                 // heap, so SetReserveSize has maximum
  1214.                                                 // space to work with
  1215.  
  1216.     if (miniInitSeg)                            // Yes, this would eventually get purged
  1217.                                                 // if the space was needed badly enough,
  1218.                                                 // but that happens very late in the game
  1219.                                                 // and can confound the unwary
  1220.         EmptyHandle(miniInitSeg);
  1221. #endif
  1222.     
  1223.     InstallGrowZoneProc();
  1224.  
  1225.     SetReserveSize(codeRes, lowSpaceRes);
  1226.     if (!pOKCodeReserve)                        // couldn't get code reserve. Can't
  1227.     {                                              // continue
  1228.         Failure(memFullErr, 0);
  1229.     }
  1230.     else
  1231.     {
  1232. #if !qPowerPC
  1233.         // Set up the LoadSeg patch 
  1234.  
  1235. #if qModelFarCode
  1236.         // Use the cool new RTLib so graciously
  1237.         // provided by Landon and Sandra
  1238.         RTPB anRTPB;
  1239.         
  1240.         // Install the preload handler
  1241.         anRTPB.fOperation = kRTSetPreLoad;
  1242.         anRTPB.fRTParam.fSegLoadParam.fUserHdlr = (SegLoadHdlrPtr) StripLong(PreloadHandler);
  1243.         if (Runtime(&anRTPB) != noErr)
  1244.             Failure(minErr, 0);
  1245.         oldPreLoadHandler = anRTPB.fRTParam.fSegLoadParam.fOldUserHdlr;
  1246.  
  1247.         // Install the postload handler
  1248.         anRTPB.fOperation = kRTSetPostLoad;
  1249.         anRTPB.fRTParam.fSegLoadParam.fUserHdlr = (SegLoadHdlrPtr) StripLong(PostloadHandler);
  1250.         if (Runtime(&anRTPB) != noErr)
  1251.             Failure(minErr, 0);    
  1252.         oldPostLoadHandler = anRTPB.fRTParam.fSegLoadParam.fOldUserHdlr;
  1253.  
  1254.         pSegLoadPatch.LookupOldTrapAddress(_LoadSeg);
  1255. #else
  1256.         FailOSErr(pSegLoadPatch.PatchTrap(_LoadSeg, ALoadMacAppSeg));
  1257. #endif
  1258. #endif
  1259.     }
  1260.  
  1261. #if !qPowerPC
  1262.     UnloadAllSegments();                        // unload one more time so memory is as clean as possible
  1263. #endif
  1264.     
  1265.     // Here is a trick suggested by Jerome C.--it allocates one large block of master
  1266.     // pointers
  1267.     applZone = ApplicationZone();
  1268.     oldMoreMast = applZone->moreMast;
  1269.     long numMasterPointersDesired = oldMoreMast * callsToMoreMasters;
  1270.     do {
  1271.         applZone->moreMast = (short) Min(numMasterPointersDesired, kMaxShort);
  1272.         MoreMasters();
  1273.         numMasterPointersDesired -= applZone->moreMast;
  1274.     } while (numMasterPointersDesired > 0);
  1275.     applZone->moreMast = oldMoreMast;
  1276.  
  1277. #if !qPowerPC
  1278.     LoadResidentSegments();
  1279. #endif
  1280.     
  1281.     gUMemoryInitialized = true;
  1282.  
  1283.     // Now fully initialized, so create our pointer based heap for object allocation.
  1284.     // Now it will come out of permanent memory.
  1285.     
  1286.     if (gObjectHeap == NULL)
  1287.     {
  1288.         gObjectHeap = new ObjectHeap((size_t)heapSize, (size_t)heapIncrement);
  1289.         gObjectHeap->IObjectHeap();
  1290.     }
  1291.     else
  1292.     {
  1293.         gObjectHeap->ExpandHeap((size_t)heapSize, (size_t)heapIncrement);
  1294.     }
  1295. } // InitUMemory 
  1296.  
  1297.  
  1298. //----------------------------------------------------------------------------------------
  1299. // LoadMacAppSegment: 
  1300. //----------------------------------------------------------------------------------------
  1301. #if !qPowerPC
  1302. #pragma push
  1303. #pragma trace off
  1304.  
  1305. #pragma segment MAMemoryRes
  1306. // must be in Main segment 
  1307.  
  1308. pascal UniversalProcPtr LoadMacAppSegment(short segnum)
  1309. {
  1310. #if qDebug
  1311.     short id;
  1312.     ResType kind;
  1313.     CStr255 segName;
  1314.     MAName s;
  1315.     Handle seg;
  1316. #endif
  1317.  
  1318.     long A5RegisterOnEntry = SetCurrentA5();            // ***** Called from trap patches *****
  1319.  
  1320.     UniversalProcPtr loadMacAppSegment = pSegLoadPatch.GetOldTrapAddr();// Where to go next 
  1321.  
  1322.     if (GetA5() != A5RegisterOnEntry)
  1323.     {
  1324.         // not called from our application… don't do patch behaviour. Thank you McSink! 
  1325.         pLoadSegCalledFromOwnApp = false;
  1326.         SetA5(A5RegisterOnEntry);
  1327.     }
  1328.     else
  1329.         {
  1330.         pLoadSegCalledFromOwnApp = true;
  1331.         pOldResFile = MAUseResFile(gCodeRefNum);// Must set a global because we return
  1332.                                                 // from this function and then forward to
  1333.                                                 // the actual segment loader which should
  1334.                                                 // also be pointing to the _now_ correct
  1335.                                                 // resfile. When we get called back again
  1336.                                                 // in PostLoadMacAppSegment we will
  1337.                                                 // restore the old resFile as the current
  1338.                                                 // resFile. Sorry about the global.
  1339.  
  1340.         if (!PreloadSegmentResource(segnum))
  1341.         {
  1342. #if qDebug
  1343.             GetCallersMethodName(s);
  1344.             SetResLoad(false);
  1345.             seg = MAGet1Resource(kCode, segnum);
  1346.  
  1347.             GetResInfo(seg, &id, &kind, segName);
  1348.             SetResLoad(true);
  1349. //###SRF            ProgramBreak("In " + s + form(" couldn't load segment: %d", segnum) + segName);
  1350. #endif
  1351.  
  1352.             Failure(memFullErr, 0);
  1353.         }
  1354.  
  1355.         (*gIsLoadedSeg)[segnum - 1] = true;
  1356.  
  1357. #if qDebug
  1358.         if (gSegReport)
  1359.         {
  1360.             GetResInfo((*gCodeSegs)[segnum - 1], &id, &kind, segName);
  1361.             fprintf(stderr, "  *** Segment Loaded: %d %s\n", segnum, (char *) segName);
  1362.         }
  1363. #endif
  1364.  
  1365.     }
  1366.  
  1367.     return loadMacAppSegment;
  1368. } // LoadMacAppSegment 
  1369.  
  1370. #pragma pop
  1371. #endif
  1372.  
  1373. //----------------------------------------------------------------------------------------
  1374. // LoadResidentSegments: 
  1375. //----------------------------------------------------------------------------------------
  1376. #if !qPowerPC
  1377. #pragma segment MAMemoryRes
  1378. // Must be in Main segment 
  1379.  
  1380. void LoadResidentSegments()
  1381. {
  1382.     short offset, 
  1383.     segnum, 
  1384.     rsrcCnt;
  1385.     Handle nameList,  seg;
  1386.     SignedBytePtr p;
  1387.     CStr255 name;
  1388.     ResType theType;
  1389.     char savedState;
  1390.  
  1391.     rsrcCnt = CountResources('res!');
  1392.     for (short resIndex = 1; resIndex <= rsrcCnt; ++resIndex)
  1393.     {
  1394.         nameList = GetIndResource('res!', resIndex);
  1395.         savedState = HGetState(nameList);
  1396.         HNoPurge(nameList);
  1397.  
  1398.         offset = 2;
  1399.         short numNames = *((IntegerPtr) * nameList);
  1400.         for (short i = 1; i <= numNames; ++i)
  1401.         {
  1402.             p = (SignedBytePtr)(*nameList + offset);
  1403.             BlockMove(p, &name, *p + 1);
  1404.             offset += name.Length() + 1;
  1405.  
  1406.             seg = MAGet1NamedResource(kCode, name);
  1407.  
  1408.             if (seg)
  1409.             {
  1410.                 GetResInfo(seg, &segnum, &theType, name);
  1411. #ifdef __MWERKS__
  1412.                 if (IsHandleLocked(seg))    // if its locked, then jump table is already set up
  1413.                     (*gIsResidentSeg)[segnum - 1] = true;
  1414.                 else                
  1415. #endif
  1416.                     SetResidentSegment(segnum, true);
  1417.             }
  1418.         }
  1419.  
  1420.         HSetState(nameList, savedState);
  1421.         ReleaseResource(nameList);
  1422.     }
  1423. } // LoadResidentSegments 
  1424. #endif
  1425.  
  1426. //----------------------------------------------------------------------------------------
  1427. // MemSpaceIsLow: 
  1428. //----------------------------------------------------------------------------------------
  1429. #pragma segment MAMemoryRes
  1430.  
  1431. Boolean MemSpaceIsLow()
  1432. {
  1433.     BuildAllReserves();
  1434.     return IsHandlePurged(pMemReserve);
  1435. } // MemSpaceIsLow 
  1436.  
  1437. //----------------------------------------------------------------------------------------
  1438. // NewPermHandle: 
  1439. //----------------------------------------------------------------------------------------
  1440. #pragma segment MAMemoryRes
  1441.  
  1442. Handle NewPermHandle(Size logicalSize)
  1443. {
  1444.     static const short initVal = 0xF3;            // odd at all byte boundaries            
  1445.  
  1446.     Boolean priorPerm;
  1447.     Handle aHandle;
  1448.  
  1449.     priorPerm = PermAllocation(true);
  1450.     aHandle = NewHandle(logicalSize);
  1451.     pPermAllocation = priorPerm;
  1452.     FailNIL(aHandle);
  1453. #if qDebug
  1454.     BlockSet(*aHandle, logicalSize, initVal);
  1455. #endif
  1456.     return aHandle;
  1457. } // NewPermHandle 
  1458.  
  1459. //----------------------------------------------------------------------------------------
  1460. // NewPermPtr: 
  1461. //----------------------------------------------------------------------------------------
  1462. #pragma segment MAMemoryRes
  1463.  
  1464. Ptr NewPermPtr(Size logicalSize)
  1465. {
  1466.     static const short initVal = 0xF3;            // odd at all byte boundaries            
  1467.  
  1468.     Boolean priorPerm;
  1469.     Ptr aPtr;
  1470.  
  1471.  
  1472.     priorPerm = PermAllocation(true);
  1473.     aPtr = NewPtr(logicalSize);
  1474.     pPermAllocation = priorPerm;
  1475.     FailNIL(aPtr);
  1476. #if qDebug
  1477.     BlockSet(aPtr, logicalSize, initVal);
  1478. #endif
  1479.     return aPtr;
  1480. } // NewPermPtr 
  1481.  
  1482. //----------------------------------------------------------------------------------------
  1483. // PermAllocation: 
  1484. //----------------------------------------------------------------------------------------
  1485. #pragma segment MAMemoryRes
  1486.  
  1487. Boolean PermAllocation(Boolean permanent)
  1488. {
  1489.     Boolean permAllocation = pPermAllocation;
  1490.  
  1491.     if (permanent != pPermAllocation)
  1492.     {
  1493.         pPermAllocation = permanent;
  1494.         if (permanent)
  1495.             BuildCodeReserve(kGZMaxAlloc, false);
  1496.     }
  1497.  
  1498.     return permAllocation;
  1499. } // PermAllocation 
  1500.  
  1501. //----------------------------------------------------------------------------------------
  1502. // PermHandToHand: 
  1503. //----------------------------------------------------------------------------------------
  1504. #pragma segment MAMemoryRes
  1505.  
  1506. void PermHandToHand(Handle& theHndl) 
  1507. {
  1508.     Boolean priorPerm;
  1509.     OSErr err;
  1510.     
  1511.     priorPerm = PermAllocation(true);
  1512.     err = HandToHand(&theHndl);
  1513.     pPermAllocation = priorPerm;
  1514.     
  1515.     FailOSErr(err);    
  1516.     
  1517. } // PermHandToHand 
  1518.  
  1519.  
  1520. //========================================================================================
  1521. // struct CWithCodeResFileDo
  1522. //========================================================================================
  1523.  
  1524. struct CWithCodeResFileDo
  1525. {
  1526. public:
  1527.     short &fSegNum;
  1528.     Handle &fSeg;
  1529.     
  1530.     CWithCodeResFileDo(short &segnum,
  1531.                        Handle &seg)
  1532.         :
  1533.         fSegNum(segnum),
  1534.           fSeg(seg)
  1535.         {
  1536.         }
  1537. };
  1538.  
  1539. //----------------------------------------------------------------------------------------
  1540. // DoGetSegHandle: 
  1541. //----------------------------------------------------------------------------------------
  1542. #pragma segment MAMemoryRes
  1543. // must be in Main segment 
  1544.  
  1545. void DoGetSegHandle(void* scopeLink)
  1546. {
  1547.     CWithCodeResFileDo* segInfo = (CWithCodeResFileDo*)scopeLink;
  1548.     
  1549.     short saveResLoad = LMGetResLoad();
  1550.     SetResLoad(true);                            // yes, we really *do* want it.
  1551.     segInfo->fSeg = Get1Resource(kCode, segInfo->fSegNum);
  1552.     SetResLoad(saveResLoad);
  1553. } // DoGetSegHandle 
  1554.  
  1555.  
  1556. //========================================================================================
  1557. // GLOBAL Procedures
  1558. //========================================================================================
  1559. #undef Inherited
  1560.  
  1561. //----------------------------------------------------------------------------------------
  1562. // PreloadSegmentResource: 
  1563. //----------------------------------------------------------------------------------------
  1564. #if !qPowerPC
  1565. #pragma segment MAMemoryRes
  1566. // must be in Main segment 
  1567.  
  1568. pascal Boolean PreloadSegmentResource(short segnum)
  1569. {
  1570.     Handle seg;
  1571.     CWithCodeResFileDo scopeLink(segnum, seg);
  1572.  
  1573. #if qDebug
  1574.     if (pPermAllocation)
  1575.     {
  1576.         if (!((*gIsResidentSeg)[segnum - 1]))
  1577.         {
  1578.             fprintf(stderr, "segment # = %d\n", segnum);
  1579.             ProgramBreak("Trying to load a segment with PermAllocation == true.");
  1580.         }
  1581.     }
  1582. #endif
  1583.  
  1584.     WithCodeResFileDo(&DoGetSegHandle, &scopeLink);
  1585.  
  1586.     if (!seg)
  1587.         return false;
  1588.     else
  1589.     {
  1590.         if (!IsHandleLocked(seg))                // not yet locked 
  1591.             LockHandleHigh(seg);
  1592.         HNoPurge(seg);
  1593.         return true;
  1594.     }
  1595. } // PreloadSegmentResource 
  1596. #endif
  1597.  
  1598. //----------------------------------------------------------------------------------------
  1599. // ScanList: 
  1600. //----------------------------------------------------------------------------------------
  1601. #pragma segment MAMemoryRes
  1602.  
  1603. typedef Handle *HandlePtr;
  1604.  
  1605. void ScanList(HandleListHandle list,
  1606.               DoToHandlesType DoToHandle,
  1607.               void *scopeLink)
  1608. {
  1609.     HandlePtr p = (HandlePtr) * list;
  1610.  
  1611.     for (short i = (short)(GetHandleSize((Handle)list) / sizeof(Handle)); i > 0; --i, ++p)
  1612.     {
  1613.         DoToHandle(*p, scopeLink);
  1614.     }
  1615. } // ScanList 
  1616.  
  1617.  
  1618. //----------------------------------------------------------------------------------------
  1619. // ScanHandles: 
  1620. //----------------------------------------------------------------------------------------
  1621. void ScanHandles(DoToHandlesType DoToHandle,
  1622.                  void *staticLink)
  1623. {
  1624. #if !qPowerPC
  1625.     ScanList(gCodeSegs, DoToHandle, staticLink);
  1626. #endif
  1627.     
  1628.     if (gApp1MemList)
  1629.         ScanList(gApp1MemList, DoToHandle, staticLink);
  1630.     ScanList(gSysMemList, DoToHandle, staticLink);
  1631.     if (gApp2MemList)
  1632.         ScanList(gApp2MemList, DoToHandle, staticLink);
  1633. } // ScanHandles 
  1634.  
  1635. //----------------------------------------------------------------------------------------
  1636. // SetPermHandleSize: 
  1637. //----------------------------------------------------------------------------------------
  1638. #pragma segment MAMemoryRes
  1639.  
  1640. void SetPermHandleSize(Handle h, Size newSize)
  1641. {
  1642.     static const short initVal = 0xF3;
  1643.  
  1644.     Boolean priorPerm;
  1645. #if qDebug
  1646.     Size oldSize;
  1647. #endif
  1648.  
  1649.     priorPerm = PermAllocation(true);
  1650. #if qDebug
  1651.     oldSize = GetHandleSize(h);
  1652. #endif
  1653.  
  1654.     SetHandleSize(h, newSize);
  1655.     pPermAllocation = priorPerm;        // Since we are in the memory unit we can break
  1656.                                         // the encapsulation of the PermAllocation Call to
  1657.                                         // just set the pPermAllocation flag back
  1658.                                         // directly. This lets us be assured that no
  1659.                                         // operations have occurred that would invalidate
  1660.                                         // the MemErr flag thus the following call will
  1661.                                         // give a true result
  1662.     FailMemError();
  1663. #if qDebug
  1664.     if (oldSize < newSize)
  1665.         BlockSet((Ptr) * h + oldSize, newSize - oldSize, initVal);
  1666. #endif
  1667.  
  1668. } // SetPermHandleSize 
  1669.  
  1670. //----------------------------------------------------------------------------------------
  1671. // SetPermPtrSize: 
  1672. //----------------------------------------------------------------------------------------
  1673. #pragma segment MAMemoryRes
  1674.  
  1675. void SetPermPtrSize(Ptr p, Size newSize)
  1676. {
  1677.     static const short initVal = 0xF5;
  1678.  
  1679.     Boolean priorPerm;
  1680. #if qDebug
  1681.     Size oldSize;
  1682. #endif
  1683.  
  1684.     priorPerm = PermAllocation(true);
  1685. #if qDebug
  1686.     oldSize = GetPtrSize(p);
  1687. #endif
  1688.  
  1689.     SetPtrSize(p, newSize);
  1690.     pPermAllocation = priorPerm;        // Since we are in the memory unit we can break
  1691.                                         // the encapsulation of the PermAllocation Call to
  1692.                                         // just set the pPermAllocation flag back
  1693.                                         // directly. This lets us be assured that no
  1694.                                         // operations have occurred that would invalidate
  1695.                                         // the MemErr flag thus the following call will
  1696.                                         // give a true result
  1697.     FailMemError();
  1698. #if qDebug
  1699.     if (oldSize < newSize)
  1700.         BlockSet((Ptr)p + oldSize, newSize - oldSize, initVal);
  1701. #endif
  1702.  
  1703. } // SetPermPtrSize 
  1704.  
  1705. //----------------------------------------------------------------------------------------
  1706. // SetReserveSize: 
  1707. //----------------------------------------------------------------------------------------
  1708. #pragma segment MAMemoryRes
  1709.  
  1710. void SetReserveSize(Size forCode, Size forOther)
  1711. {
  1712. #if !qPowerPC
  1713.     pSzCodeReserve = forCode;
  1714. #endif
  1715.     pSzMemReserve = forOther;
  1716.  
  1717.     // Since the numbers have changed, make sure we start from scratch. 
  1718.     pReserveExists = false;
  1719.     EmptyHandle(pMemReserve);
  1720.  
  1721.     BuildAllReserves();
  1722. } // SetReserveSize 
  1723.  
  1724. //----------------------------------------------------------------------------------------
  1725. // SetResidentSegment: 
  1726. //----------------------------------------------------------------------------------------
  1727. #if !qPowerPC
  1728. #pragma segment MAMemoryRes
  1729.  
  1730. // must be in Main segment 
  1731.  
  1732. void SetResidentSegment(short segnum, Boolean makeResident)
  1733. {
  1734. #if qDebug
  1735.     short id;
  1736.     ResType kind;
  1737.     CStr255 segName;
  1738.     MAName s;
  1739.     Handle seg;
  1740. #endif
  1741.  
  1742.     if (makeResident)
  1743.     {
  1744.         (*gIsResidentSeg)[segnum - 1] = true;
  1745.         if (!PreloadSegment(segnum))
  1746.         {
  1747. #if qDebug
  1748.             GetCallersMethodName(s);
  1749.             SetResLoad(false);
  1750.             seg = MAGet1Resource(kCode, segnum);
  1751.             SetResLoad(true);
  1752.             GetResInfo(seg, &id, &kind, segName);
  1753. //###SRF            ProgramBreak("In " + s + form(" couldn't load segment: %d", segnum) + segName);
  1754. #endif
  1755.  
  1756.             Failure(memFullErr, 0);
  1757.         }
  1758.     }
  1759.     else
  1760.         (*gIsResidentSeg)[segnum - 1] = false;
  1761. } // SetResidentSegment 
  1762.  
  1763. #endif
  1764.  
  1765. //----------------------------------------------------------------------------------------
  1766. // SetStackSpace: 
  1767. //----------------------------------------------------------------------------------------
  1768. #pragma segment MAMiniInit
  1769.  
  1770. void SetStackSpace(long numBytes)
  1771. {
  1772.     long newLimit;
  1773.  
  1774.     // Make sure numBytes is even
  1775.     if (odd(numBytes)) numBytes++;
  1776.  
  1777.     newLimit = (long)LMGetCurStackBase() - numBytes;
  1778.     if ((long)GetApplLimit() > newLimit)
  1779.         SetApplLimit((Ptr)newLimit);
  1780. } // SetStackSpace 
  1781.  
  1782. //--------------------------------------------------------------------------------------------------
  1783.  
  1784. class CTotalTempSize
  1785. {
  1786. public:
  1787.     Boolean &fJustLocked;
  1788.     Handle &fCanPurge;
  1789.     Size &fTotal;
  1790.     THz &fApplZone;
  1791.     
  1792.     CTotalTempSize(Boolean &justLocked,
  1793.                    Handle &canPurge,
  1794.                    Size &total,
  1795.                    THz &applZone)
  1796.         :
  1797.         fJustLocked(justLocked),
  1798.           fCanPurge(canPurge),
  1799.           fTotal(total),
  1800.           fApplZone(applZone)
  1801.         {
  1802.         }
  1803. };
  1804.  
  1805.  
  1806. //----------------------------------------------------------------------------------------
  1807. // CTotalTempSize::TotalUp: 
  1808. //----------------------------------------------------------------------------------------
  1809. #pragma segment MAMemoryRes
  1810.  
  1811. void TotalUpHandleList(Handle h, void* staticLink)
  1812. {
  1813.     CTotalTempSize* tempInfo = (CTotalTempSize*)staticLink;
  1814.     Boolean hIsLocked;
  1815.  
  1816.     if (h != 0 && !IsHandlePurged(h))                // in memory already
  1817.         if (HandleZone(h) == tempInfo->fApplZone)    // in application heap 
  1818.         {
  1819.             HNoPurge(h);
  1820.  
  1821.             hIsLocked = IsHandleLocked(h);
  1822.  
  1823.             if (!tempInfo->fJustLocked || hIsLocked)
  1824.                 tempInfo->fTotal += GetHandleSize(h) + 8;
  1825.             // add in the size plus heap overhead 
  1826.  
  1827.             if (!hIsLocked)
  1828.                 if (tempInfo->fCanPurge == NULL)
  1829.                     if (IsHandleEligible(h))
  1830.                         tempInfo->fCanPurge = h;
  1831.         }
  1832. } // TotalUpHandleList 
  1833.  
  1834.  
  1835. //========================================================================================
  1836. // GLOBAL Procedures
  1837. //========================================================================================
  1838. #undef Inherited
  1839.  
  1840. //----------------------------------------------------------------------------------------
  1841. // TotalTempSize: 
  1842. //----------------------------------------------------------------------------------------
  1843. #pragma segment MAMemoryRes
  1844.  
  1845. Size TotalTempSize(Boolean justLocked,
  1846.                    Handle &canPurge)
  1847. {
  1848.     Size total;
  1849.     THz applZone;
  1850.     CTotalTempSize scopeLink(justLocked, canPurge, total, applZone);
  1851.  
  1852.     canPurge = NULL;
  1853.     total = 0;
  1854.     applZone = ApplicationZone();
  1855.  
  1856.     ScanHandles(& TotalUpHandleList, &scopeLink);
  1857.  
  1858.     return total;
  1859. } // TotalTempSize 
  1860.  
  1861. //----------------------------------------------------------------------------------------
  1862. // WithCodeResFileDo: 
  1863. //----------------------------------------------------------------------------------------
  1864. #pragma segment MAMemoryRes
  1865.  
  1866. void WithCodeResFileDo(DoWithResFileType DoWithResFile,
  1867.                         void *scopeLink)
  1868. {
  1869.     short oldResFile = MAUseResFile(gCodeRefNum);
  1870.  
  1871.     DoWithResFile(scopeLink);
  1872.  
  1873.     MAUseResFile(oldResFile);
  1874. } // WithCodeResFileDo 
  1875.  
  1876. #if !qPowerPC
  1877. #if qDebug
  1878.  
  1879. //----------------------------------------------------------------------------------------
  1880. // CheckCallChain: 
  1881. //----------------------------------------------------------------------------------------
  1882. #pragma segment MAMemoryRes
  1883. // must be in Main segment 
  1884.  
  1885. void CheckCallChain(const CStackFrame& frame, void* /* staticLink */)
  1886. {
  1887.     void *pc = frame.GetReturnAddress();
  1888.     
  1889.     short itsSeg = GetSegFromPC(pc);
  1890.     if ((itsSeg != 0) &&!(*gIsResidentSeg)[itsSeg - 1] && (*gIsLoadedSeg)[itsSeg - 1])
  1891.     {
  1892.         fprintf(stderr, "Segment#: %d\n", itsSeg);
  1893.         ProgramBreak("I really don't think that you want to unload a segment into which you are going to return!");
  1894.     }
  1895. } // CheckCallChain 
  1896.  
  1897. #endif
  1898. #endif
  1899.  
  1900. //========================================================================================
  1901. // GLOBAL Procedures
  1902. //========================================================================================
  1903. #undef Inherited
  1904.  
  1905. //----------------------------------------------------------------------------------------
  1906. // IsModelFarCodeSegment: 
  1907. //----------------------------------------------------------------------------------------
  1908. #if !qPowerPC
  1909. #pragma segment MAMemoryRes
  1910.  
  1911. inline Boolean IsModelFarCodeSegment(Handle seg)
  1912. {
  1913.     if (seg)
  1914.         return **((unsigned short **) seg) == 0xFFFF;
  1915.     else
  1916.         return false;
  1917. } // IsModelFarCodeSegment 
  1918. #endif
  1919.  
  1920.  
  1921. // must be in Main segment 
  1922.  
  1923. #if !qPowerPC
  1924. struct ModelFarCodeHeader
  1925. {
  1926.     short field1;
  1927.     short field2;
  1928.     long A5OffsetOf16BitEntries;
  1929.     long numOf16BitEntries;
  1930.     long A5OffsetOf32BitEntries;
  1931.     long numOf32BitEntries;
  1932.     char otherEvenMorePrivateStuff;            // You didn't think I would reveal any more
  1933.                                             // than I had to did you?
  1934. };
  1935.  
  1936. typedef ModelFarCodeHeader *ModelFarCodeHeaderPtr,
  1937.  **ModelFarCodeHeaderHandle;
  1938. #ifdef __MWERKS__
  1939. const short kJTSkipOver = 4; //for large model, CW looks at the 2nd long in the resource 
  1940. #else
  1941. const short kJTSkipOver = 2;                    // size of jmp (or loadseg) instruction
  1942.                                                 // that must be skipped in the JT Entry in
  1943.                                                 // order to get to the target address
  1944. #endif
  1945. #endif
  1946.  
  1947. //----------------------------------------------------------------------------------------
  1948. // DoUnloadAllSegments: 
  1949. //----------------------------------------------------------------------------------------
  1950. #if !qPowerPC
  1951.  
  1952. void DoUnloadAllSegments(void* scopeLink)
  1953. {
  1954.     long* jmpTablePtr = (long*)scopeLink;
  1955.     short i;
  1956.     Handle seg;
  1957.     for (i = 0; i < pMaxSegNum; ++i)
  1958.     {
  1959.         if (!(*gIsResidentSeg)[i] && (*gIsLoadedSeg)[i])
  1960.         {
  1961.             seg = (*gCodeSegs)[i];
  1962.             if ((seg) && !IsHandlePurged(seg))
  1963.             {
  1964.                 if (IsModelFarCodeSegment(seg))
  1965.                 {
  1966.                     if ((*((ModelFarCodeHeaderHandle)seg))->numOf16BitEntries)
  1967.                         UnloadSeg((Ptr)(*jmpTablePtr + (*((ModelFarCodeHeaderHandle) seg))->
  1968.                                         A5OffsetOf16BitEntries + kJTSkipOver));
  1969.                     else                            // Has to be the other since we wouldn't even
  1970.                         // have a segment otherwise
  1971.                         UnloadSeg((Ptr)(*jmpTablePtr + (*((ModelFarCodeHeaderHandle)seg))->
  1972.                                         A5OffsetOf32BitEntries + kJTSkipOver));
  1973.                 }
  1974.                 else
  1975.                 {
  1976. #ifdef __MWERKS__
  1977.                     long firstProcInSegment = (*(long*)((*seg) + kJTSkipOver)) + (long) GetA5();
  1978.                     UnloadSeg((Ptr)firstProcInSegment);
  1979.  
  1980. #else
  1981.                     UnloadSeg((Ptr)(*jmpTablePtr + **((IntegerHandle)seg) + kJTSkipOver));
  1982. #endif
  1983.  
  1984.                 }
  1985.                 HNoPurge(seg);
  1986.                 (*gIsLoadedSeg)[i] = false;
  1987.             }
  1988.         }
  1989.     }
  1990. } // DoUnloadAllSegments 
  1991.  
  1992. #endif
  1993.  
  1994. //========================================================================================
  1995. // GLOBAL Procedures
  1996. //========================================================================================
  1997. #undef Inherited
  1998.  
  1999. //----------------------------------------------------------------------------------------
  2000. // UnloadAllSegments: 
  2001. //----------------------------------------------------------------------------------------
  2002. #if !qPowerPC
  2003. #pragma segment MAMemoryRes
  2004. // must be in Main segment 
  2005.  
  2006. void UnloadAllSegments()
  2007. {
  2008. #if qDebug
  2009.     if (gCheckRsrcUsage)
  2010.         CheckRsrcUsage();
  2011. #endif
  2012.  
  2013.     if (gUnloadAllSegs)
  2014.     {
  2015. #if qDebug
  2016.         CStackFrame stackFrame((void *) GetCurStackFramePtr());
  2017.         EachFrameDo(stackFrame, &CheckCallChain, (void*)kNoStaticLink);
  2018. #endif
  2019.  
  2020.         long jmpTablePtr = (long) (GetA5() + LMGetCurJTOffset());
  2021.         WithCodeResFileDo(&DoUnloadAllSegments, &jmpTablePtr);
  2022.  
  2023.         if (gSegReport)
  2024.             ProgramReport("  *** Just unloaded all segments ***", gMemMgtBreak);
  2025.     }
  2026. } // UnloadAllSegments 
  2027.  
  2028. #endif
  2029.  
  2030. //----------------------------------------------------------------------------------------
  2031. // WriteReserves: fprintf's the temporary reserve and low-memory reserves to stderr
  2032. //----------------------------------------------------------------------------------------
  2033.  
  2034. #if qDebug
  2035.  
  2036. #pragma segment MADebug
  2037.  
  2038. void WriteReserves()
  2039. {
  2040.     WrLblPtr("Temporary reserve (pCodeReserve)", (long)pCodeReserve);
  2041.     fprintf(stderr, "\n");
  2042.     WrLblPtr("Low-memory reserve (pMemReserve)", (long)pMemReserve);
  2043.     fprintf(stderr, "\n");
  2044. } // WriteReserves
  2045.  
  2046. #endif
  2047.  
  2048.